package org.zoomdev.zoom.common.caster;

import org.zoomdev.zoom.common.utils.Classes;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;

class ArrayAndCollections {
    static class Array2Array implements ValueCaster {

        private final Class<?> toType;

        public Array2Array(Class<?> toType) {
            this.toType = toType;
        }

        @Override
        public Object to(Object src) {
            int len = Array.getLength(src);
            Object array = Array.newInstance(toType, len);
            for (int i=0;i<len;++i) {
                Array.set(array, i, Caster.toType(Array.get(src,i), toType));
            }
            return array;
        }
    }


    static class Array2ParameterizedType implements ValueCaster {

        private final Class<?> collectionType;
        private final Type elementType;

        public Array2ParameterizedType(Class<?> collectionType, Type elementType) {
            this.collectionType = collectionType;
            this.elementType = elementType;
        }

        @Override
        public Object to(Object src) {
            Object[] it = (Object[]) src;
            Collection<?> collection = Classes.newCollection(collectionType);
            for (Object i : it) {
                collection.add(Caster.toType(i, elementType));
            }

            return collection;
        }
    }

    static class Iterable2Array implements ValueCaster {

        private final Class<?> toType;

        public Iterable2Array(Class<?> toType) {
            this.toType = toType;
        }

        @Override
        public Object to(Object src) {
            Iterable<?> iterable = (Iterable<?>) src;
            ArrayList<?> list = new ArrayList<>();
            for (Object data : iterable) {
                list.add(Caster.toType(data, toType));
            }
            //array
            Object array = Array.newInstance(toType, list.size());
            list.toArray((Object[]) array);
            return array;
        }
    }

    static class Iterable2Collection implements ValueCaster {

        private final Class<? extends Collection> collectionClass;
        private final Type objectType;

        public Iterable2Collection(Class<? extends Collection> collectionClass, Type objectType) {
            this.collectionClass = collectionClass;
            this.objectType = objectType;
        }

        @Override
        public Object to(Object src) {
            Iterable<?> it = (Iterable<?>) src;
            Collection<?> result = Classes.newCollection(collectionClass);
            for (Object data : it) {
                result.add(Caster.toType(data, objectType));
            }
            return result;
        }
    }
}
